package com.kuangjia.conferenceroomrental.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.kuangjia.conferenceroomrental.entity.Reservation;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 预约 Mapper 接口
 */
@Mapper
public interface ReservationMapper extends BaseMapper<Reservation> {
    
    /**
     * 根据用户ID查询预约
     */
    @Select("SELECT * FROM reservations WHERE user_id = #{userId} ORDER BY created_at DESC")
    List<Reservation> selectByUserId(@Param("userId") Long userId);
    
    /**
     * 根据会议室ID查询预约
     */
    @Select("SELECT * FROM reservations WHERE room_id = #{roomId} ORDER BY start_time ASC")
    List<Reservation> selectByRoomId(@Param("roomId") Long roomId);
    
    /**
     * 根据状态查询预约
     */
    @Select("SELECT * FROM reservations WHERE status = #{status} ORDER BY created_at DESC")
    List<Reservation> selectByStatus(@Param("status") String status);
    
    /**
     * 检查时间冲突 - 重叠时间段检测
     * 会议室相同 AND 状态为待审批或已批准 AND 时间段重叠
     *
     * 时间段重叠的条件: NOT (end_time <= startTime OR start_time >= endTime)
     * 这个条件等价于: start_time < endTime AND end_time > startTime
     */
    @Select("SELECT COUNT(*) FROM reservations r JOIN rooms rm ON r.room_id = rm.id " +
            "WHERE r.room_id = #{roomId} AND r.status IN ('PENDING', 'APPROVED') " +
            "AND NOT (r.end_time <= #{startTime} OR r.start_time >= #{endTime})")
    int checkTimeConflict(@Param("roomId") Long roomId, 
                         @Param("startTime") LocalDateTime startTime, 
                         @Param("endTime") LocalDateTime endTime);
                         
    /**
     * 根据会议室名称查询预约冲突
     *
     * 时间段重叠的条件与上面相同:
     * NOT (end_time <= startTime OR start_time >= endTime)
     */
    @Select("SELECT COUNT(*) FROM reservations r " +
            "JOIN rooms rm ON r.room_id = rm.id " +
            "WHERE rm.name = #{roomName} AND r.status IN ('PENDING', 'APPROVED') " +
            "AND NOT (r.end_time <= #{startTime} OR r.start_time >= #{endTime})")
    int checkTimeConflictByRoomName(@Param("roomName") String roomName, 
                                  @Param("startTime") LocalDateTime startTime, 
                                  @Param("endTime") LocalDateTime endTime);
    
    /**
     * 获取冲突的预约详情 - 包含会议室名称
     * 返回所有与当前时间段重叠的预约
     */
    @Select("SELECT r.*, rm.name as room_name FROM reservations r " +
            "JOIN rooms rm ON r.room_id = rm.id " +
            "WHERE r.room_id = #{roomId} AND r.status IN ('PENDING', 'APPROVED') " +
            "AND NOT (r.end_time <= #{startTime} OR r.start_time >= #{endTime}) " +
            "ORDER BY r.start_time ASC")
    List<Reservation> getConflictingReservations(@Param("roomId") Long roomId, 
                                              @Param("startTime") LocalDateTime startTime, 
                                              @Param("endTime") LocalDateTime endTime);
    
    /**
     * 获取与指定会议室名称冲突的预约
     */
    @Select("SELECT r.*, rm.name as room_name FROM reservations r " +
            "JOIN rooms rm ON r.room_id = rm.id " +
            "WHERE rm.name = #{roomName} AND r.status IN ('PENDING', 'APPROVED') " +
            "AND NOT (r.end_time <= #{startTime} OR r.start_time >= #{endTime}) " +
            "ORDER BY r.start_time ASC")
    List<Reservation> getConflictingReservationsByRoomName(@Param("roomName") String roomName, 
                                                        @Param("startTime") LocalDateTime startTime, 
                                                        @Param("endTime") LocalDateTime endTime);
    
    /**
     * 精确的时间范围查询 - 直接查找在某个时间范围内的预约
     * 用于单元测试与调试
     */
    @Select("SELECT r.*, rm.name as room_name FROM reservations r " +
            "JOIN rooms rm ON r.room_id = rm.id " +
            "WHERE r.room_id = #{roomId} AND r.status IN ('PENDING', 'APPROVED') " +
            "AND ((r.start_time <= #{endTime} AND r.start_time >= #{startTime}) " +
            "     OR (r.end_time <= #{endTime} AND r.end_time >= #{startTime}) " +
            "     OR (r.start_time <= #{startTime} AND r.end_time >= #{endTime}))")
    List<Reservation> findReservationsInTimeRange(@Param("roomId") Long roomId, 
                                               @Param("startTime") LocalDateTime startTime, 
                                               @Param("endTime") LocalDateTime endTime);
} 